
#ifndef __RISCV_DEBUG_H__
#define __RISCV_DEBUG_H__

//
// Riscv debug
// DTM
//
#define RISCV_DTM_JTAG_REG_IDCODE       0x01
#define RISCV_DTM_JTAG_REG_DTMCS        0x10
#define RISCV_DTM_JTAG_REG_DMI          0x11
#define RISCV_DTM_JTAG_REG_BYPASS       0x1f

#define RISCV_DTMCS_DMIRESET            (1 << 16)
#define RISCV_DTMCS_DMIHARDRESET        (1 << 17)

typedef union 
{
    uint32_t reg;
    struct 
    {
        uint32_t version: 4;
        uint32_t abits: 6;
        uint32_t dmistat: 2;
        uint32_t idle: 3;
        uint32_t reserved15: 1;
        uint32_t dmireset: 1;
        uint32_t dmihardreset: 1;
        uint32_t reserved18: 14;
    };
} riscv_dtmcs_t;

//
// Riscv debug
// DMI
//
#define RISCV_DMI_OP_NOP        0
#define RISCV_DMI_OP_READ       1
#define RISCV_DMI_OP_WRITE      2

#define RISCV_DMI_RESULT_DONE   0
#define RISCV_DMI_RESULT_FAIL   2
#define RISCV_DMI_RESULT_BUSY   3

//
// Riscv debug
// DM
//
#define RISCV_DM_DATA0          0x04 // Abstract Data 0 (data0)
#define RISCV_DM_DATA1          0x05
#define RISCV_DM_DATA2          0x06
#define RISCV_DM_DATA3          0x07
#define RISCV_DM_DATA4          0x08
#define RISCV_DM_DATA5          0x09
#define RISCV_DM_DATA6          0x0a
#define RISCV_DM_DATA7          0x0b
#define RISCV_DM_DATA8          0x0c
#define RISCV_DM_DATA9          0x0d
#define RISCV_DM_DATA10         0x0e
#define RISCV_DM_DATA11         0x0f // Abstract Data 11 (data11)

#define RISCV_DM_CONTROL        0x10 // Debug Module Control (dmcontrol)
#define RISCV_DM_STATUS         0x11 // Debug Module Status (dmstatus)
#define RISCV_DM_HART_INFO      0x12 // Hart Info (hartinfo)
#define RISCV_DM_HART_SUM1      0x13 // Halt Summary 1 (haltsum1)
#define RISCV_DM_HA_WINDOW_SEL  0x14 // Hart Array Window Select (hawindowsel)
#define RISCV_DM_HA_WINDOW      0x15 // Hart Array Window (hawindow)
#define RISCV_DM_ABSTRACT_CS    0x16 // Abstract Control and Status (abstractcs)
#define RISCV_DM_ABSTRACT_CMD   0x17 // Abstract Command (command)
#define RISCV_DM_ABSTRACT_AUTO  0x18 // Abstract Command Autoexec (abstractauto)
#define RISCV_DM_CONF_STR_PTR0  0x19 // Configuration String Pointer 0 (confstrptr0)
#define RISCV_DM_CONF_STR_PTR1  0x1a
#define RISCV_DM_CONF_STR_PTR2  0x1b
#define RISCV_DM_CONF_STR_PTR3  0x1c // Configuration String Pointer 3 (confstrptr3)
#define RISCV_DM_NEXT           0x1d // Next Debug Module (nextdm)

#define RISCV_DM_PROG_BUF0      0x20 // Program Buffer 0 (progbuf0)
#define RISCV_DM_PROG_BUF1      0x21
#define RISCV_DM_PROG_BUF2      0x22
#define RISCV_DM_PROG_BUF3      0x23
#define RISCV_DM_PROG_BUF4      0x24
#define RISCV_DM_PROG_BUF5      0x25
#define RISCV_DM_PROG_BUF6      0x26
#define RISCV_DM_PROG_BUF7      0x27
#define RISCV_DM_PROG_BUF8      0x28
#define RISCV_DM_PROG_BUF9      0x29
#define RISCV_DM_PROG_BUF10     0x2a
#define RISCV_DM_PROG_BUF11     0x2b
#define RISCV_DM_PROG_BUF12     0x2c
#define RISCV_DM_PROG_BUF13     0x2d
#define RISCV_DM_PROG_BUF14     0x2e
#define RISCV_DM_PROG_BUF15     0x2f // Program Buffer 15 (progbuf15)

#define RISCV_DM_AUTH_DATA      0x30 // Authentication Data (authdata)
#define RISCV_DM_HALT_SUM2      0x34 // Halt Summary 2 (haltsum2)
#define RISCV_DM_HALT_SUM3      0x35 // Halt Summary 3 (haltsum3)
#define RISCV_DM_SB_ADDR3       0x37 // System Bus Address 127:96 (sbaddress3)
#define RISCV_DM_SB_CS          0x38 // System Bus Access Control and Status (sbcs)
#define RISCV_DM_SB_ADDR0       0x39 // System Bus Address 31:0 (sbaddress0)
#define RISCV_DM_SB_ADDR1       0x3a // System Bus Address 63:32 (sbaddress1)
#define RISCV_DM_SB_ADDR2       0x3b // System Bus Address 95:64 (sbaddress2)

#define RISCV_DM_SB_DATA0       0x3c // System Bus Data 31:0 (sbdata0)
#define RISCV_DM_SB_DATA1       0x3d
#define RISCV_DM_SB_DATA2       0x3e
#define RISCV_DM_SB_DATA3       0x3f // System Bus Data 127:96 (sbdata3)

#define RISCV_DM_HAL_SUM0       0x40 // Halt Summary 0 (haltsum0)


// Abstract Command (command)
#define RISCV_DM_ABSTRACT_CMD_ACCESS_REG        0
#define RISCV_DM_ABSTRACT_CMD_QUICK_ACCESS      1
#define RISCV_DM_ABSTRACT_CMD_ACCESS_MEM        2


typedef uint32_t riscv_dmi_reg_t;
typedef uint32_t riscv_csr_reg_t;
typedef union
{
    riscv_dmi_reg_t reg;
    struct {
        unsigned int dmactive: 1;
        unsigned int ndmreset: 1;
        unsigned int clrresethaltreq: 1;
        unsigned int setresethaltreq: 1;
        unsigned int reserved4: 2;
        unsigned int hartselhi: 10;
        unsigned int hartsello: 10;
        unsigned int hasel: 1;
        unsigned int reserved27: 1;
        unsigned int ackhavereset: 1;
        unsigned int hartreset: 1;
        unsigned int resumereq: 1;
        unsigned int haltreq: 1;
    };
}riscv_dmcontrol_t;


typedef union
{
    riscv_dmi_reg_t reg;
    struct {
        unsigned int version: 4;
        unsigned int confstrptrvalid: 1;
        unsigned int hasresethaltreq: 1;
        unsigned int authbusy: 1;
        unsigned int authenticated: 1;
        unsigned int anyhalted: 1;
        unsigned int allhalted: 1;
        unsigned int anyrunning: 1;
        unsigned int allrunning: 1;
        unsigned int anyunavail: 1;
        unsigned int allunavail: 1;
        unsigned int anynonexistent: 1;
        unsigned int allnonexistent: 1;
        unsigned int anyresumeack: 1;
        unsigned int allresumeack: 1;
        unsigned int anyhavereset: 1;
        unsigned int allhavereset: 1;
        unsigned int reserved20: 2;
        unsigned int impebreak: 1;
        unsigned int reserved23: 9;
    };
}riscv_dmstatus_t;


typedef union
{
    riscv_dmi_reg_t reg;
    struct {
        unsigned int dataaddr: 12;
        unsigned int datasize: 4;
        unsigned int dataaccess: 1;
        unsigned int reserved17: 3;
        unsigned int nscratch: 4;
        unsigned int reserved24: 8;
    };
}riscv_hartinfo_t;


typedef union
{
    riscv_dmi_reg_t reg;
    struct {
        unsigned int datacount: 4;
        unsigned int reserved4: 4;
        unsigned int cmderr: 3;
        unsigned int reserved11: 1;
        unsigned int busy: 1;
        unsigned int reserved13: 11;
        unsigned int progbufsize: 5;
        unsigned int reserved29: 3;
    };
}riscv_abstractcs_t;


#define RISCV_DM_CMD_REG        0   // Access Register Command
#define RISCV_DM_CMD_QUICK      1   // Quick Access
#define RISCV_DM_CMD_MEM        2   // Access Memory Command


typedef union
{
    riscv_dmi_reg_t reg;
    struct {
        unsigned int control: 24;
        unsigned int cmdtype: 8;
    };
}riscv_command_t;


typedef union
{
    riscv_dmi_reg_t reg;
    struct {
        unsigned int regno: 16;
        unsigned int write: 1;
        unsigned int transfer: 1;
        unsigned int postexec: 1;
        unsigned int aarpostincrement: 1;
        unsigned int aarsize: 3;
        unsigned int reserved23: 1;
        unsigned int cmdtype: 8;
    };
}riscv_command_access_register_t;


typedef union
{
    riscv_dmi_reg_t reg;
    struct {
        unsigned int reserved0: 24;
        unsigned int cmdtype: 8;
    };
}riscv_command_quick_access_t;


typedef union
{
    riscv_dmi_reg_t reg;
    struct {
        unsigned int reserved0: 14;
        unsigned int target_specific: 2;
        unsigned int write: 1;
        unsigned int reserved17: 2;
        unsigned int aampostincrement: 1;
        unsigned int aamsize: 3;
        unsigned int aamvirtual: 1;
        unsigned int cmdtype: 8;
    };
}riscv_command_access_memory_t;


typedef union
{
    riscv_dmi_reg_t reg;
    struct {
        unsigned int autoexecdata: 12;
        unsigned int reserved12: 4;
        unsigned int autoexecprogbuf: 16;
    };
}riscv_abstractauto_t;


typedef union
{
    riscv_dmi_reg_t reg;
    struct {
        unsigned int sbaccess8: 1;
        unsigned int sbaccess16: 1;
        unsigned int sbaccess32: 1;
        unsigned int sbaccess64: 1;
        unsigned int sbaccess128: 1;
        unsigned int sbasize: 7;
        unsigned int sberror: 3;
        unsigned int sbreadondata: 1;
        unsigned int sbautoincrement: 1;
        unsigned int sbaccess: 3;
        unsigned int sbreadonaddr: 1;
        unsigned int sbbusy: 1;
        unsigned int sbbusyerror: 1;
        unsigned int reserved23: 6;
        unsigned int sbversion: 3;
    };
}riscv_sbcs_t;


typedef struct
{
    riscv_dmi_reg_t reserved_0x00[4];
    riscv_dmi_reg_t data[12];
    riscv_dmcontrol_t dmcontrol;
    riscv_dmstatus_t dmstatus;
    riscv_hartinfo_t hartinfo;
    riscv_dmi_reg_t haltsum1;
    riscv_dmi_reg_t hawindowsel;
    riscv_dmi_reg_t hawindow;
    riscv_abstractcs_t abstractcs;
    union {
        riscv_command_t command;
        riscv_command_access_register_t command_access_register;
        riscv_command_quick_access_t command_quick_access;
        riscv_command_access_memory_t command_access_memory;
    };
    riscv_abstractauto_t abstractauto;
    riscv_dmi_reg_t confstrptr[4];
    riscv_dmi_reg_t nextdm;
    riscv_dmi_reg_t reserved_0x1f[1];
    riscv_dmi_reg_t progbuf[16];
    riscv_dmi_reg_t authdata;
    riscv_dmi_reg_t reserved_0x31[3];
    riscv_dmi_reg_t haltsum2;
    riscv_dmi_reg_t haltsum3;
    riscv_dmi_reg_t reserved_0x36[1];
    riscv_dmi_reg_t sbaddress3;
    riscv_sbcs_t sbcs;
    riscv_dmi_reg_t sbaddress[3];
    riscv_dmi_reg_t sbdata[4];
    riscv_dmi_reg_t haltsum0;
}riscv_dm_t;

typedef uint32_t riscv_register_t;
typedef uint32_t riscv_mem_t;

typedef union
{
    riscv_csr_reg_t reg;
    struct {
        unsigned int load: 1;
        unsigned int store: 1;
        unsigned int execute: 1;
        unsigned int u: 1;
        unsigned int s: 1;
        unsigned int reserved5: 1;
        unsigned int m: 1;
        unsigned int match: 4;
        unsigned int chain: 1;
        unsigned int action: 4;
        unsigned int sizelo: 2;
        unsigned int timing: 1;
        unsigned int select: 1;
        unsigned int hit: 1;
        unsigned int maskmax: 6;
        unsigned int dmode: 1;
        unsigned int type: 4;      
    };
} riscv_csr_mcontrol_t;

typedef union
{
    riscv_csr_reg_t reg;
    struct {
        unsigned int prv: 2;
        unsigned int step: 1;
        unsigned int nmip: 1;
        unsigned int mprven: 1;
        unsigned int reserved5: 1;
        unsigned int cause: 3;
        unsigned int stoptime: 1;
        unsigned int stopcount: 1;
        unsigned int stepie: 1;
        unsigned int ebreaku: 1;
        unsigned int ebreaks: 1;
        unsigned int reserved14: 1;
        unsigned int ebreakm: 1;
        unsigned int reserved16: 12;
        unsigned int xdebugver: 4;
    };
} riscv_csr_dcsr_t;

typedef struct 
{
    char hwnum;
    char breaknum;
    struct
    {
        char hwno;
        char enable;
        char type; // 0-hwbreak 1-watchpoint(write) 2-watchpoint(read) 3-watchpoint(access) 4-swbreak
        uint32_t addr32;
        uint64_t addr64;
    } info[32]
} riscv_breakpiont_t;

extern void riscv_dtm_idcode(uint32_t *_idcode);
extern void riscv_dtm_dtmcs(riscv_dtmcs_t *_dtmcs);
//extern void riscv_dtm_dtmcs_dmireset(void);
//extern void riscv_dtm_dtmcs_dmihardreset(void);
//extern void riscv_dtm_dmi(uint32_t addr, uint32_t *data, uint32_t *op);
//extern void riscv_dmi_nop(void);
//extern void riscv_dmi_read(uint32_t addr, uint32_t *data, uint32_t *result);
//extern void riscv_dmi_write(uint32_t addr, uint32_t data, uint32_t *result);
extern void riscv_debug_init(void);
extern int riscv_debug_halt(void);
extern int riscv_debug_halt_check(uint32_t *_stat);
extern int riscv_debug_resume(unsigned char *_pc, char _flag);
extern int riscv_debug_resume_check(uint32_t *_stat);
extern int riscv_debug_reset(char _flag);
extern int riscv_debug_read_register(uint8_t *_reg, uint32_t _regno, uint32_t _regsz);
extern int riscv_debug_write_register(uint8_t *_reg, uint32_t _regno, uint32_t _regsz);
extern int riscv_debug_read_mem(riscv_mem_t _memaddr, void *buf, uint32_t _bytes);
extern int riscv_debug_write_mem(riscv_mem_t _memaddr, void *_buf, uint32_t _bytes);
extern int riscv_debug_breakpiont(unsigned char *addr, char point_type, char set_clr);
extern int riscv_debug_halt_reason(void);
extern int riscv_debug_step(char flag);

extern int riscv_debug_sysbus_write_mem(unsigned int adr, unsigned char *buf, unsigned int sz, unsigned int crc_flag);

extern riscv_dtmcs_t dtmcs;
extern riscv_dm_t riscv_dm;

#define CSR_MSTATUS    (0x300+65)
#define CSR_TSELECT    (0x7A0+65)
#define CSR_TDATA1     (0x7A1+65)
#define CSR_TDATA2     (0x7A2+65)
#define CSR_TINFO      (0x7A4+65)
#define CSR_DPC        (0x7B1+65)
#define CSR_DCSR       (0x7B0+65)

#endif
